package com.example.demo.controller;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.cert.CertificateException;
import java.util.AbstractMap.SimpleEntry;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeoutException;

import org.hyperledger.fabric.gateway.Contract;
import org.hyperledger.fabric.gateway.ContractException;
import org.hyperledger.fabric.gateway.Gateway;
import org.hyperledger.fabric.gateway.Network;
import org.hyperledger.fabric.gateway.Wallet;
import org.hyperledger.fabric.gateway.Wallets;
import org.hyperledger.fabric.sdk.exception.CryptoException;
import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
import org.hyperledger.fabric_ca.sdk.exception.EnrollmentException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.HttpUtil;
import com.example.demo.service.Alice;
import com.example.demo.service.AuthorizationService;
import com.example.demo.service.FileModel;
import com.example.demo.service.LedgerServices;
import com.example.demo.service.ProxyReEncrypt;
import com.example.demo.service.PubParams;
import com.example.demo.service.SystemProperty;

import it.unisa.dia.gas.jpbc.Element;
import net.sf.json.JSONArray;

@RestController
public class AliceController {
	private Alice a;
	 private AuthorizationService authorizationService;
	    private LedgerServices ledgerServices;

	    @Autowired
	    public AliceController(AuthorizationService authorizationService, LedgerServices ledgerServices) {
	        this.authorizationService = authorizationService;
	        this.ledgerServices = ledgerServices;
	        try {
	        	this.authorizationService.enrollAdmin();
	        	this.authorizationService.registerUser();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
	    }
	

	@RequestMapping(value = "/alice/encrypt", method = { RequestMethod.POST })
	public void encrypt(@RequestBody String content) throws IOException {
		ProxyReEncrypt  d=new ProxyReEncrypt ();
		PubParams p=null;
		try {
			p=d.read();// IO
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		int m=SystemProperty.getIntegerValue("m");
		int t=SystemProperty.getIntegerValue("t");
		//Bob b=BobController.getBob();
		this.a=new Alice(p,m,t);
		a.FileEncrypt(content);
		// 上传元数据
		try {
			ledgerServices.createCar(new FileModel("key", "filePath", "fileMd5", "owner", "fileName","accessID"));
		} catch (ContractException | IOException | TimeoutException | InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		a.setReceivers(getIDs());//IO to Fabric
		
		Element A=getA(a.getReceivers());//IO to Fabric
		a.RkGen(A);
		a.dec();
		
	}
	public void upload() throws IOException {
		// Load a file system based wallet for managing identities.
			Path walletPath = Paths.get("wallet");
			Wallet wallet = Wallets.newFileSystemWallet(walletPath);
			// load a CCP
			Path networkConfigPath = Paths.get("..", "..", "test-network", "organizations", "peerOrganizations", "org1.example.com", "connection-org1.yaml");

			Gateway.Builder builder = Gateway.createBuilder();
			builder.identity(wallet, "appUser").networkConfig(networkConfigPath).discovery(true);

			// create a gateway connection
			try (Gateway gateway = builder.connect()) {

				// get the network and contract
				Network network = gateway.getNetwork("mychannel");
				Contract contract = network.getContract("fabFileModel");

				byte[] result;

				result = contract.evaluateTransaction("queryAllFiles");
				System.out.println(new String(result));
				contract.submitTransaction("createFileModel", "File3", "VW2", "Polo2", "xxx2","mm2","Mary2");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}
	public Element getA(List<Element> receivers) {
		List<String> ids=new LinkedList<>();
		StringBuilder sb=new StringBuilder();
		sb.append('[');
		for(int i=0;i<receivers.size()-1;i++) {
			//System.out.println(receivers.get(i));
				String s=receivers.get(i).toString();//new String(receivers.get(i).toBytes(),"ISO-8859-1");
				sb.append(s);
				sb.append(',');
			
		}
		if(receivers.size()>0) sb.append(receivers.get(receivers.size()-1).toString());
			
		sb.append(']');
		String response=HttpUtil.sendPost("http://localhost:8082/A", sb.toString());
		try {
			return a.p.Zr.newElementFromBytes(response.getBytes("ISO-8859-1"));
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
		
	}
	public List<Element> getIDs() {

		try {
			String response=HttpUtil.sendGet("http://localhost:8082/ids","UTF-8");
			JSONArray ja = JSONArray.fromObject(response);
			
			List<Element> ids=new LinkedList<>();
			for(int i=0;i<ja.size();i++) {
				Element id=a.p.Zr.newElementFromBytes(ja.getString(i).getBytes("ISO-8859-1"));
				ids.add(id);
			}
			return ids;
			
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
    
}
